import Vue from 'vue';
import { addClass, removeClass, getStyle } from '@/utils/dom';
import afterLeave from 'element-ui/src/utils/after-leave';
import Loading from './loading.vue';

const insertDom = (parent, el, binding) => {
  // eslint-disable-next-line no-underscore-dangle
  const _el = el;
  if (!_el.domVisible && getStyle(_el, 'display') !== 'none' && getStyle(_el, 'visibility') !== 'hidden') {
    // 赋值style
    Object.keys(_el.maskStyle).forEach((property) => {
      _el.mask.style[property] = _el.maskStyle[property];
    });

    if (_el.originalPosition !== 'absolute' && _el.originalPosition !== 'fixed') {
      addClass(parent, 'loading-parent--relative');
    }
    if (binding.modifiers.fullscreen && binding.modifiers.lock) {
      addClass(parent, 'el-loading-parent--hidden');
    }
    _el.domVisible = true;
    if (!_el.domInserted) {
      parent.appendChild(_el.mask);
    }
    if (!_el.domInserted && binding.modifiers.lock) {
      _el.mask.addEventListener('wheel', (e) => {
        e.preventDefault();
      });
    }
    Vue.nextTick(() => {
      _el.instance.visible = true;
    });
    _el.domInserted = true; // 是否已插入loading遮罩层
  } else if (_el.domVisible) {
    _el.instance.visible = true;
  }
};
const Mask = Vue.extend(Loading);
const toggleLoading = (el, binding) => {
  // eslint-disable-next-line no-underscore-dangle
  const _el = el;
  if (binding.value) {
    Vue.nextTick(() => {
      if (binding.modifiers.fullscreen) {
        _el.originalPosition = getStyle(document.body, 'position');

        addClass(_el.mask, 'is-fullscreen');
        insertDom(document.body, _el, binding);
      } else {
        removeClass(_el.mask, 'is-fullscreen');
        if (binding.modifiers.body) {
          _el.originalPosition = getStyle(document.body, 'position');

          ['top', 'left'].forEach((property) => {
            const scroll = property === 'top' ? 'scrollTop' : 'scrollLeft';
            _el.maskStyle[property] = `${
              _el.getBoundingClientRect()[property] + document.body[scroll] + document.documentElement[scroll] - parseInt(getStyle(document.body, `margin-${property}`), 10)
            }px`;
          });
          ['height', 'width'].forEach((property) => {
            _el.maskStyle[property] = `${_el.getBoundingClientRect()[property]}px`;
          });

          insertDom(document.body, _el, binding);
        } else {
          _el.originalPosition = getStyle(_el, 'position');
          insertDom(el, _el, binding);
        }
      }
    });
  } else {
    afterLeave(
      el.instance,
      () => {
        const target = binding.modifiers.fullscreen || binding.modifiers.body ? document.body : el;
        removeClass(target, 'loading-parent--relative');
        removeClass(target, 'loading-parent--hidden');
      },
      300,
      true,
    );
    _el.domVisible = false;
    _el.instance.visible = false;
  }
};

export default {
  // eslint-disable-next-line no-unused-vars
  bind(el, binding, vnode) {
    // eslint-disable-next-line no-underscore-dangle
    const _el = el;
    const mask = new Mask().$mount();
    _el.instance = mask;
    _el.mask = mask.$el;
    _el.maskStyle = {};

    if (binding.value) {
      toggleLoading(_el, binding);
    }
  },
  update(_el, binding) {
    if (binding.value !== binding.oldValue) {
      toggleLoading(_el, binding);
    }
  },
  unbind(el, binding) {
    if (el.domInserted) {
      if (el.mask && el.mask.parentNode) {
        el.mask.parentNode.removeChild(el.mask);
      }
      toggleLoading(el, {
        value: false,
        modifiers: binding.modifiers,
      });
    }
    if (el.instance) {
      el.instance.$destroy();
    }
  },
};
